package org.stvd.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Iterator;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.crypto.codec.Base64;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.stvd.common.Consts;
import org.stvd.core.dto.QueryCondition;
import org.stvd.core.util.MathUtil;
import org.stvd.core.web.CookieUtils;

import net.sf.json.JSONObject;

/**
 * 基础控制类
 */
public class BaseController {

    @Resource
    protected HttpServletRequest request;
    @Resource
    protected HttpServletResponse response;
    protected ModelMap map;
    protected Integer pageSize = 20;
    protected Integer pageNo = 1;
    private static final String reqCookieName = "reqp"; 

    @ModelAttribute
    protected void init(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
        this.response = response;
        this.map = model;
        this.pageSize = Consts.PAGE_SIZE;
        pageNo = 1;
        String url = request.getRequestURI(); 

        if (request.getMethod().equals("POST")) {
            if (!StringUtils.isEmpty(request.getParameter("pageNo"))) {
                pageNo = Integer.parseInt(request.getParameter("pageNo"));
            }
            if (request.getParameter("_STATE") != null) {
                saveRequestParameters(request, response);
            }
        } else if (request.getMethod().equals("GET")) {
            try {
                JSONObject jsonMap = getRequestParameters(request);
                if (jsonMap != null && jsonMap.containsKey("url") && jsonMap.getString("url").equals(url)) {
                    pageNo = MathUtil.parseInt(getJsonValue(jsonMap, "pageNo"), 1);
                    loadParameterData(request, jsonMap);
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace(); 
            }
        }
        this.map.put("uri", request.getRequestURI());
        this.map.put("pageNo", pageNo);
        this.map.put("pageSize", pageSize);
    }

    protected String getJsonValue(JSONObject jsonMap, String key) {
        if (jsonMap != null && jsonMap.containsKey(key)) {
            return jsonMap.get(key).toString();
        }
        return "";
    }

    /**
     * 存储当前页面中的requestParameter信息
     */
    protected void saveRequestParameters(HttpServletRequest request, HttpServletResponse response) {
        // 保存参数
        JSONObject jsonMap = new JSONObject();
        jsonMap.put("url", request.getRequestURI());
        Enumeration<String> paramNames = request.getParameterNames();
        while (paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement(); 

            String[] paramValues = request.getParameterValues(paramName);
            if (paramValues.length == 1) {
                String paramValue = paramValues[0];
                if (paramValue.length() != 0 && paramValue.length() < 200) {
                    jsonMap.put(paramName, paramValue);
                }
            }
        }
        try {

            delRequestParameters(request, response);
            
            String cookieValueBase64 = new String(Base64.encode(jsonMap.toString().getBytes("UTF-8")), "UTF-8");
            cookieValueBase64 = cookieValueBase64.replace("\r\n", "");              
            cookieValueBase64 = cookieValueBase64.replace("\n", "");     
            String cookieValueUrlEncode = URLEncoder.encode(cookieValueBase64, "UTF-8");
            
            CookieUtils.saveCookie(response, reqCookieName, cookieValueUrlEncode , null, null); 
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从临时存储中获取当前请求页面中存储的requestParameter信息
     * 
     * @param request
     * @return 以JSONObject对象返回存储的requestParameter信息
     * @throws UnsupportedEncodingException 
     */
    protected JSONObject getRequestParameters(HttpServletRequest request) throws UnsupportedEncodingException {
        String parametersStr = CookieUtils.getCookie(request, reqCookieName);
        if (!StringUtils.isEmpty(parametersStr)) {
            return JSONObject.fromObject(new String(Base64.decode(URLDecoder.decode(parametersStr, "UTF-8").getBytes("UTF-8")), "UTF-8")); 
        }
        return null;
    }

    protected void delRequestParameters(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().contains(reqCookieName)) {
                    CookieUtils.delCookie(request, response, cookie.getName());
                }
            }
        }
    }

    protected void loadParameterData(HttpServletRequest request, JSONObject jsonMap) {
        if (jsonMap != null && jsonMap.size() > 0) {
            @SuppressWarnings("unchecked")
            Iterator<String> keyIterator = jsonMap.keys();
            while (keyIterator.hasNext()) {
                String keyStr = keyIterator.next();
                if ("pageNo".equals(keyStr) || "_csrf".equals(keyStr)) {
                    continue;
                }
                this.map.put(keyStr, jsonMap.get(keyStr));
            }
        }
    }

    /**
     * 构造查询条件 type——>QUERY : 新查询 AGAIN : 在查询结果中，再次查询 EXACT : 精确查询 condition ： 查询条件，例如：name = 或 name like content ：
     * 查询内容，如果condition中包含like关键字，则内容自动增加为%content% whereStr ： 构造好的查询条件 orderStr ： 在构造查询条件中，没有使用
     */
    protected QueryCondition buildQueryCondition(QueryCondition queryCondition) {
        if (queryCondition.getType().equals("QUERY")) { // 新查询
            queryCondition.setWhereStr("where 1=1");
            if (!queryCondition.getContent().equals("")) {
                if (queryCondition.getCondition().toUpperCase().indexOf(" LIKE") > 0) {
                    queryCondition.setWhereStr(
                        " where " + queryCondition.getCondition() + " '%" + queryCondition.getContent() + "%' ");
                } else {
                    queryCondition.setWhereStr(
                        " where " + queryCondition.getCondition() + " '" + queryCondition.getContent() + "' ");
                }
            }
        } else if (queryCondition.getType().equals("AGAIN")) { // 再查询
            if (!queryCondition.getContent().equals("")) {
                if (queryCondition.getCondition().toUpperCase().indexOf(" LIKE") > 0) {
                    queryCondition.setWhereStr(queryCondition.getWhereStr() + " and " + queryCondition.getCondition()
                        + " '%" + queryCondition.getContent() + "%' ");
                } else {
                    queryCondition.setWhereStr(queryCondition.getWhereStr() + " and " + queryCondition.getCondition()
                        + " '" + queryCondition.getContent() + "' ");
                }
            }
        } else if (queryCondition.getType().equals("EXACT")) { // 精确查询
            if (!queryCondition.getContent().equals("")) {
                queryCondition.setWhereStr(" where " + queryCondition.getCondition().replace("like", "=") + " '"
                    + queryCondition.getContent() + "' ");
            }
        } else {
            queryCondition.setWhereStr("where 1=1");
        }

        return queryCondition;
    }

    /**
     * 初始化的数据类型的绑定值 整型Integer：如果格式不正确，则自动转为0； 长整型Long，如果格式不正确，则自动转为0； 浮点型Double，如果格式不正确，则自动转为0；
     * 
     * @param binder
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        // SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd
        // HH:mm:ss");
        // binder.registerCustomEditor(Date.class, new
        // CustomDateEditor(dateFormat, false));
        // 字符串，如果不为空，则自动trim空格，为空返回空字符串；
        binder.registerCustomEditor(String.class, DataBinderSupport.StringEditor);
        // 整型，如果格式不正确，则自动转为0；
        binder.registerCustomEditor(Integer.class, DataBinderSupport.IntegerEditor);
        // 长整型，如果格式不正确，则自动转为0；
        binder.registerCustomEditor(Long.class, DataBinderSupport.LongEditor);
        // 浮点型，如果格式不正确，则自动转为0；
        binder.registerCustomEditor(Double.class, DataBinderSupport.DoubleEditor);
    }

}
